home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 355_02 / slk2.exe / SPP / SYS.C < prev    next >
C/C++ Source or Header  |  1991-06-09  |  19KB  |  940 lines

  1. /*
  2.     New Sherlock Preprocessor -- system module.
  3.  
  4.     Source:  sys.c
  5.     Started: October 7, 1985
  6.     Version:
  7.         July 20, 1988;
  8.         November 1, 1988  bug fix: extra '\r' in sysnlput().
  9.         February 10, 1989 bug fix:  kludge in sysopen().
  10.         February 16, 1989
  11.             periods removed from error messages.
  12.             t_line bug fixed in sysopen().
  13.         June 22, 1989
  14.             backslash newlines now filtered by sysnext().
  15.         August 3, 1989
  16.             signal code added to syscsts().
  17.             errors written to stderr.
  18.  
  19.  
  20.     PUBLIC DOMAIN SOFTWARE
  21.  
  22.     Sherlock, including the SPP, SDEL and SDIF programs, was placed in
  23.     the public domain on June 15, 1991, by its author,
  24.  
  25.         Edward K. Ream
  26.         166 North Prospect Ave.
  27.         Madison, WI 53705.
  28.         (608) 257-0802
  29.  
  30.     Sherlock may be used for any commercial or non-commercial purpose.
  31.  
  32.  
  33.     DISCLAIMER OF WARRANTIES
  34.  
  35.     Edward K. Ream (Ream) specifically disclaims all warranties,
  36.     expressed or implied, with respect to this computer software,
  37.     including but not limited to implied warranties of merchantability
  38.     and fitness for a particular purpose.  In no event shall Ream be
  39.     liable for any loss of profit or any commercial damage, including
  40.     but not limited to special, incidental consequential or other damages.
  41. */
  42.  
  43. #include "spp.h"
  44.  
  45. #ifdef MICRO_SOFT
  46. #include <signal.h>
  47. #include <fcntl.h>
  48. #include <sys\types.h>
  49. #include <sys\stat.h>
  50. #include <io.h>
  51. #include <time.h>
  52. #endif
  53.  
  54. #ifdef TURBOC
  55. #include <signal.h>
  56. #include <fcntl.h>
  57. #include <sys\stat.h>
  58. #include <io.h>
  59. #include <conio.h>
  60. #include <time.h>
  61. #endif
  62.  
  63. /*
  64.     Define the format of a file node.
  65.     The node contains all information pertaining to the file.
  66.     The fil_name and f_line are used to update preprocessor globals.
  67. */
  68. typedef enum { NULL_STAT,
  69.     CLOSED_STAT, INPUT_STAT, OUTPUT_STAT, LOCAL_STAT, EOF_STAT
  70. } en_stat;
  71.  
  72. static struct FN {
  73.     struct FN * f_next;    /* pointer to next node        */
  74.     char *    fil_name;    /* file name            */
  75.     int    f_line;        /* line number            */
  76.     char *    f_buffer;    /* file buffer            */
  77.     int    f_bufsize;    /* size of file buffer: bytes    */
  78.     int    f_handle;    /* handle to file.        */
  79.     char *  f_bufp;        /* pointer into file buffer    */
  80.     int    f_bufc;        /* characters in buffer        */
  81.     en_stat    f_type;        /* status of file        */
  82.     int    f_lastc;    /* restart character        */
  83. };
  84. #define FN_SIZE (sizeof(struct FN))
  85.  
  86. static struct FN * in_list   = NULL;    /* List of input nodes.        */
  87. static struct FN * outn_list = NULL;    /* List of output nodes.    */
  88.  
  89. /*
  90.     The following global variables are copies of the fields in FN.
  91.     Global variables are used as an efficiency measure.
  92. */
  93. static char *    s_ip = NULL;    /* Copy of f_bufp for input file.    */
  94. static int    s_ic = 0;        /* Copy of f_bufc for input file.    */
  95. static char *    s_op = NULL;    /* Copy of f_bufp for output file.    */
  96. static int    s_oc = 0;    /* Copy of f_bufc for output file.    */
  97.  
  98. #define MAX_INLEVEL 20    /* Max depth of nested #includes.    */
  99. #define IBUF_SIZE 2048    /* Size of each input buffer.        */
  100. #define OBUF_SIZE 2048    /* Size of the output buffer.        */
  101.  
  102. /*
  103.     Define "pushed back" characters used by sysn1().
  104. */
  105. static int    push_back = -1;        /* Used by macro logic.        */
  106. static int    file_put_back = -1;    /* Used by non-macro logic.    */
  107.  
  108. /*
  109.     Define variables used by time and date routines.
  110. */
  111. static    long ltime;
  112. static    struct tm *newtime;
  113. static char time_buf [30];
  114. static char date_buf [30];
  115.  
  116. /*
  117.     Declare static functions in this module.
  118. */
  119. static void    raw_close    (int);
  120. static int    raw_creat    (char *);
  121. static int    raw_open    (char *);
  122. static int    raw_read    (int, char *, int);
  123. static int    raw_write    (int, char *, int);
  124. static int    syscstat    (void);
  125. static void    sysn1        (void);
  126. static struct FN *sys_new    (int);
  127. static void    sys_release    (void);
  128.  
  129. /*
  130.     Close a file opened with raw_open() or raw_creat().
  131. */
  132. static void
  133. raw_close(handle)
  134. int handle;
  135. {
  136.     TRACEP("raw_close", printf("(handle: %d)\n", handle));
  137.  
  138.     close (handle);
  139. }
  140.  
  141. /*
  142.     Open the file for writing only.
  143.     Return a handle (int) or ERROR.
  144. */
  145. static int
  146. raw_creat(name)
  147. char *name;
  148. {
  149.  
  150.     TRACEP("raw_creat", printf("(%s)\n", name));
  151.  
  152.     chmod(name, S_IREAD | S_IWRITE);
  153.     return creat(name, S_IREAD | S_IWRITE);
  154. }
  155.  
  156. /*
  157.     Open the file for reading only.
  158.     Return a handle (int) or ERROR.
  159. */
  160. static int
  161. raw_open(name)
  162. char *name;
  163. {
  164.     TRACEP("raw_open", printf("(%s)\n", name));
  165.  
  166.     return open(name, O_RDONLY | O_BINARY);
  167. }
  168.  
  169. /*
  170.     Read n bytes from the file described by handle into buffer[].
  171.     Return the number of bytes read.
  172. */
  173. static int
  174. raw_read(handle, buffer, n)
  175. int handle;
  176. char *buffer;
  177. int n;
  178. {
  179.     int result;
  180.  
  181.     TRACEP("raw_read", printf("(handle: %d, buffer: %lx, n: %d)\n",
  182.         handle, buffer, n));
  183.         
  184.     result = read (handle, buffer, n);
  185.  
  186.     TRACEP("raw_read", printf("returns %d\n", result));
  187.     return result;
  188. }
  189.  
  190. /*
  191.     Write n bytes from buffer[] to the file described by handle.
  192.     Return the number of bytes written.
  193. */
  194. static int
  195. raw_write(handle, buffer, n)
  196. int handle;
  197. char *buffer;
  198. int n;
  199. {
  200.     TRACEP("raw_write", printf("(handle: %dx, buffer: %lx, n: %d)\n",
  201.         handle, buffer, n));
  202.         
  203.     return write (handle, buffer, n);    
  204. }
  205.  
  206. /*
  207.     Close all files and exit.
  208.  
  209.     Do not call fatal() or sysabort() from inside
  210.     sysiclose(), sysoclose(), or sys_release().
  211. */
  212. void
  213. sysabort()
  214. {
  215.     /* Close the output file. */
  216.     if (outn_list != NULL) {
  217.         sysoclose();
  218.     }
  219.  
  220.     /* Close all input files. */
  221.     while(in_list != NULL) {
  222.         sysiclose();
  223.     }
  224.     sysend();
  225.     exit(BAD_EXIT);
  226. }        
  227.  
  228. /*
  229.     Put a non-newline to the output file.
  230.     This is the second most called routine after sysnext().
  231. */
  232. void
  233. syscput(c)
  234. char c;
  235. {
  236.     struct FN * fnp;
  237.  
  238.     *s_op++ = c;
  239.     s_oc++;
  240.     if (s_oc == OBUF_SIZE) {
  241.  
  242.         fnp = outn_list;
  243.         if (raw_write(fnp->f_handle, fnp->f_buffer, OBUF_SIZE) != 
  244.             OBUF_SIZE) {
  245.             error("Disk full");
  246.             return;
  247.         }
  248.         
  249.         s_oc = 0;
  250.         s_op = fnp -> f_buffer;
  251.     }
  252. }
  253.  
  254. /*
  255.     Open a file for output.  Only one such file may be open at a time.
  256.  
  257.     Return TRUE if all went well.
  258. */
  259. bool
  260. syscreat(name)
  261. register char * name;
  262. {
  263.     register struct FN * fnp;
  264.     int handle;
  265.  
  266.     TRACEP("syscreat", printf("(%s)\n", name));
  267.  
  268.     fnp = outn_list;
  269.     if (fnp == NULL) {
  270.         /* Allocate node for output file. */
  271.         fnp = outn_list  = sys_new(OBUF_SIZE);
  272.     }
  273.     else if (fnp -> f_type != CLOSED_STAT) {
  274.         syserr("syscreat: Can't happen");
  275.     }
  276.     
  277.     /* Actually open the file. */
  278.     handle = raw_creat(name);
  279.     if (handle == ERROR) {
  280.         return FALSE;
  281.     }
  282.     fnp -> f_handle = handle;
  283.     fnp -> f_type = OUTPUT_STAT;
  284.  
  285.     /* The output buffer is empty. */
  286.     s_oc = 0;
  287.     s_op = fnp -> f_buffer;
  288.  
  289.     return TRUE;
  290. }
  291.  
  292. /*
  293.     Return 0 if no character is ready from the keyboard.
  294.     Otherwise, return the character itself.
  295. */
  296. static int sys_inited = 0;
  297.  
  298. /*
  299.     Interrupt handler for control-c.
  300. */
  301. static void
  302. ctrl_handler(int sig)
  303. {
  304.     fprintf(stderr, "\nSPP terminated by operator\n");
  305.     exit(0);
  306. }
  307.  
  308. void
  309. syscsts()
  310. {
  311.     if (sys_inited == 0) {
  312.         sys_inited = 1;
  313.         if (signal(SIGINT, ctrl_handler) == SIG_ERR) {
  314.             fprintf(stderr, "\nsignal failed.\n");
  315.             exit(-1);
  316.             sysabort();
  317.         }
  318.     }
  319. }
  320.  
  321. #if 0 /* Machine independent version.  Old code. */
  322. static int
  323. syscstat()
  324. {
  325.     if (kbhit()) {
  326.         return fgetchar() & 0x7f;
  327.     }
  328.     else {
  329.         return 0;
  330.     }
  331. }
  332.  
  333. /*
  334.     Get console status and pause if the user has hit control S.
  335.     Abort if user has hit control C.
  336. */
  337.  
  338. #define CONTROL_C 3
  339.  
  340. void
  341. syscsts()
  342. {
  343.     int c;
  344.  
  345.     c = syscstat();
  346.     if (c == CONTROL_C) {
  347.         fprintf(stderr, "\nSPP terminated by operator\n");
  348.         sysabort();
  349.     }
  350. }
  351. #endif /* old code */
  352.  
  353. /*
  354.     Return the print string of the current date.
  355. */
  356. char *
  357. sysdate()
  358. {
  359.     char *p;
  360.  
  361.     time(<ime);    
  362.     newtime = localtime(<ime);
  363.     p = asctime(newtime);
  364.     if (strlen(p) != 25) {
  365.         return "";
  366.     }
  367.     else {
  368.         strcpy(date_buf, "\"");
  369.         p[11] = '\0';
  370.         strcat(date_buf, p);
  371.         p[24] = '\0';
  372.         strcat(date_buf, p + 20);
  373.         strcat(date_buf, "\"");
  374.  
  375.         TRACEPN("sysdate", printf("returns: %s\n", date_buf));
  376.         return date_buf;
  377.     }
  378. }
  379.  
  380. /*
  381.     Shut down the system.  This routine is called just before doing an
  382.     exit().  Do any last minute things here.
  383. */
  384. void
  385. sysend()
  386. {
  387.     TICK("sysend");
  388. }
  389.  
  390. /*
  391.     Push c back into the file input stream